#include "MotorAtaque.h"
#include "Cerdito.h"
#include "HuevoCodorniz.h"

using namespace TP::Juego::Arena::Utilidades;
using namespace std;
using namespace TP::Juego::Motorizacion;

MotorAtaque::MotorAtaque() { }

MotorAtaque::~MotorAtaque() { }

Ticks MotorAtaque::notificacionAvanceTiempo(Ticks pTiempo) { }

Partida* MotorAtaque::correrPartida(Partida* pPartida, Ticks pTiempo) { }

void MotorAtaque::atacar(Jugador* pJugador, const string& pNombrePartida,
		Posicion* pPosicion) throw (Excepcion&) {
	// Identifico la partida que se encuentra jugando el jugador.
	Partida* partida = this->getPartidaPorJugador(pJugador);
	if (NULL == partida)
		throw Excepcion("Error en ataque. El jugador no se encuentra jugando"
				" partida alguna.");

	if (partida->getNombre() != pNombrePartida)
		throw Excepcion("Error en ataque. El jugador no se encuentra jugando"
				" la partida " + pNombrePartida);

	// Identifico el cerdito que se encuentra jugando el jugador.
	Cerdito* cerdito = (Cerdito*)partida->getCerditoPorJugador(pJugador);

	if (NULL == cerdito)
		throw Excepcion("Error de ataque.  El jugador " +
				pJugador->getNombre() + "no posee un cerdito designado.");

	// --------------------------------------------------
	// Se reunen las condiciones para ejecutar el ataque.
	// --------------------------------------------------

	// Lanzo el huevo que tiene cargado la catapulta.
	Huevo* huevo = (Huevo*)cerdito->getCatapulta()->getProyectil();
	if (huevo)
		this->lanzarHuevo(partida, huevo, pPosicion);

	// Cargo la catapulta con el proximo huevo.
	cerdito->getCatapulta()->setProyectil(cerdito->getCanasta()->getHuevo());
}

void MotorAtaque::lanzarHuevo(Partida* pPartida, Huevo* pHuevo,
		Posicion* pPosicionBlanco) {

	/* Para el caso especial del huevo codorniz, hay que clonarlo al menos 3 
	 * veces y agregarlo al escenario con las trayectorias configuradas.
	 * 
	 * El huevo debe haberse obtenido de la canasta por lo que la trayectoria es
	 * constante y tiene configurada como posicion inicial la posicion desde donde
	 * sale disparado el huevo.
	 */

	if (pHuevo->getRol()->Nombre() != HUEVOCODORNIZ) {
		Vector2D* velocidad = new Vector2D(pPosicionBlanco->X() - 
				pHuevo->getTrayectoria()->getPosicionInicial()->X(),
				pPosicionBlanco->Y() - pHuevo->getTrayectoria(
				)->getPosicionInicial()->Y());

		//Posicion* pPosicion, Vector2D* pVelocidad, Vector2D* pAceleracio
		pHuevo->setTrayectoria(new Trayectoria(pHuevo->getTrayectoria(
			)->getPosicionInicial(), velocidad, new Vector2D(0, 0)));
	}
	else if (pHuevo->getRol()->Nombre() == HUEVOCODORNIZ) {
		/* El huevo codorniz es una metralla de huevos.  Se implementa clonando
		 * el huevo codorniz en la arena de juego
		 * variando la dirección para cada huevo.
		 */

		// Calculo el vector direccion al blanco.
		Vector2D aux = *pPosicionBlanco - *(pHuevo->getTrayectoria(
				)->getPosicion());
		Vector2D direccion = aux.direccion();

		// Clono el huevo codorniz.
		Huevo* clon = new HuevoCodorniz();
		clon->deElementoXML(pHuevo->aElementoXML());

		// Agrego el clon a la arena de juego.
		Vector2D* velocidad = new Vector2D(cos(direccion.angulo()*0.8),
				sin(direccion.angulo() * 1.4));
		*velocidad = *velocidad * VELOCIDAD_MOD;
		pPartida->ArenaJuego()->addActor(clon, clon->getTrayectoria(
			)->getPosicionInicial(), velocidad, new Vector2D(0, 0));

		// Clono el huevo codorniz.
		clon = new HuevoCodorniz();
		clon->deElementoXML(pHuevo->aElementoXML());

		// Agrego el clon a la arena de juego.
		velocidad = new Vector2D(cos(direccion.angulo()*0.8),
				sin(direccion.angulo() * 1.1));
		*velocidad = *velocidad * VELOCIDAD_MOD;
		pPartida->ArenaJuego()->addActor(clon, clon->getTrayectoria(
			)->getPosicionInicial(), velocidad, new Vector2D(0, 0));

		// Clono el huevo codorniz.
		clon = new HuevoCodorniz();
		clon->deElementoXML(pHuevo->aElementoXML());

		// Agrego el clon a la arena de juego.
		velocidad = new Vector2D(cos(direccion.angulo()*0.8),
				sin(direccion.angulo() * 0.8));
		*velocidad = *velocidad * VELOCIDAD_MOD;
		pPartida->ArenaJuego()->addActor(clon, clon->getTrayectoria(
			)->getPosicionInicial(), velocidad, new Vector2D(0, 0));

		// Agrego el huevo codorniz a la arena de juego.
		velocidad = new Vector2D(cos(direccion.angulo()), sin(direccion.angulo()));
		*velocidad = *velocidad * VELOCIDAD_MOD;
		pPartida->ArenaJuego()->addActor(pHuevo, pHuevo->getTrayectoria(
			)->getPosicionInicial(), velocidad, new Vector2D(0, 0));
	}
}

Partida* MotorAtaque::getPartidaPorJugador(Jugador* pJugador) {
	// Por defecto el jugador no pertenece a partida alguna.
	Partida* partida = NULL;
	for (vector<Partida*>::iterator it = this->getPartidas().begin();
			it != this->getPartidas().end() && NULL == partida; ++it) {
		Partida* partidaAux = (*it);
		for (size_t curJugadores = 0; curJugadores < partidaAux->getJugadores(
				).size(); curJugadores++) {
			if (*partidaAux->getJugadores()[curJugadores] == *pJugador) {
				partida = partidaAux;
				break;
			}
		}
	}
	return partida;
}

vector<Partida*>& MotorAtaque::getPartidas() {
	return this->_motorJuego->getPartidas();
}